package com.niiwoo.civet.account.service.local.refund.newRefund;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.niiwoo.activity.event.constant.BizEventRabbitConstant;
import com.niiwoo.activity.event.dto.request.RechargeEventReqDTO;
import com.niiwoo.activity.event.enums.RechargeTypeEventEnum;
import com.niiwoo.activity.event.enums.UserRoleTypeEventEnum;
import com.niiwoo.activity.event.enums.YesOrNoEnum;
import com.niiwoo.civet.account.dao.entity.*;
import com.niiwoo.civet.account.dao.mapper.*;
import com.niiwoo.civet.account.dto.bill.AddBillAndChangeBalanceDTO;
import com.niiwoo.civet.account.dto.bill.AddBillDetailDTO;
import com.niiwoo.civet.account.dto.common.AccountBatchTransOrderDTO;
import com.niiwoo.civet.account.dto.common.MoneyTotalDTO;
import com.niiwoo.civet.account.dto.request.RechargeRecordRequestDTO;
import com.niiwoo.civet.account.dto.request.SaveAccountBillRequest;
import com.niiwoo.civet.account.enums.*;
import com.niiwoo.civet.account.service.local.AccountBalanceLocalService;
import com.niiwoo.civet.account.service.local.MoneyTotalLocalService;
import com.niiwoo.civet.account.service.local.bill.BillFacade;
import com.niiwoo.civet.account.service.local.bill.NiiwooBillFacade;
import com.niiwoo.civet.base.enums.ChannelCodeEnum;
import com.niiwoo.civet.trade.dto.common.BatchTransOrderDetailForAccountDTO;
import com.niiwoo.civet.trade.enums.BatchRefundTypeEnum;
import com.niiwoo.civet.trade.enums.RepayStatusEnum;
import com.niiwoo.civet.trade.service.refund.RepaymentDubboService;
import com.niiwoo.tripod.lanmao.enums.PreprocessingBusinessTypeEnum;
import com.niiwoo.tripod.lanmao.enums.TransactionTypeEnum;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.util.*;

/**
 * Created by dell on 2018/1/31.
 * 提供还款基础服务(单事物)
 */
@Slf4j
@Service
public class RefundBaseLocalService {

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private BatchTransOrderDetailMapperExt batchTransOrderDetailMapperExt;
    @Autowired
    private AccountBaseMapperExt accountBaseMapperExt;
    @Autowired
    private BatchTransOrderDetailBizMapper batchTransOrderDetailBizMapperExt;
    @Autowired
    private NiiwooBillFacade niiwooBillFacade;
    @Autowired
    private BillFacade billFacade;
    @Autowired
    private BatchTransOrderMapperExt batchTransOrderMapperExt;
    @Autowired
    private ProTransactionOrderMapperExt proTransactionOrderMapperExt;
    @Autowired
    private AccountBalanceLocalService accountBalanceLocalService;
    @Autowired
    private MoneyTotalLocalService moneyTotalLocalService;
    @Autowired
    private WithholdOrderMapperExt withholdOrderMapperExt;
    @Reference(version = "1.0.0")
    private RepaymentDubboService repaymentDubboService ;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private BankTypeMapperExt bankTypeMapperExt;
    @Autowired
    private PayChannelMapperExt payChannelMapperExt;


    /**
     * 保存分账明细订单数据
     * @param batchTransOrderDetailForAccountDTO
     * @param dto
     */
    @Transactional
    public void insertOrderDetailsAndSaveBills(BatchTransOrderDetailForAccountDTO batchTransOrderDetailForAccountDTO, AccountBatchTransOrderDTO dto) {
//        log.info("保存分账明细数据,batchRequestNo={}",dto.getBatchRequestNo());
//        if (!CollectionUtils.isEmpty(batchTransOrderDetailForAccountDTO.getBatchTransOrderDetails())) {
//            log.info("分账结果数据保存,projectId={}",dto.getProjectId());
//            BigDecimal capitalRefundAll = BigDecimal.ZERO;
//            BigDecimal interestRefundAll = BigDecimal.ZERO;
//            BigDecimal penaltyRefundAll = BigDecimal.ZERO;
//            BigDecimal managerFeeRefundAll = BigDecimal.ZERO;
//            BigDecimal guaranteeFeeRefundAll = BigDecimal.ZERO;
//            for (BatchTransOrderDetailDTO detailDTO : batchTransOrderDetailForAccountDTO.getBatchTransOrderDetails()) {
//                if (!CollectionUtils.isEmpty(detailDTO.getBatchTransOrderDetailBizs())) {
//                    BatchTransOrderDetail detail = new BatchTransOrderDetail();
//                    //如果取明细中当前期（多期逾期时必须）,否则直接取标的当前期数
//                    //Integer currentPeriod = detailDTO.getCurrentPeriod()!=null? detailDTO.getCurrentPeriod():dto.getCurrentPeriod();
//                    BeanUtils.copyProperties(detailDTO, detail);
//                    detail.setId(snowflakeIdWorker.nextId());
//                    detail.setStatus(RefundStatusEnum.HANDLING.getValue());
//                    detail.setBatchOrderId(dto.getBatchTransOrderId());
//                    detail.setCreateTime(new Date());
//                    detail.setTradeType(TransactionTypeEnum.valueOf(detailDTO.getTradeTypeStr()).getValue());
//                    batchTransOrderDetailMapperExt.insertSelective(detail);
//
//                    for (BatchTransOrderDetailBizDTO bizDTO : detailDTO.getBatchTransOrderDetailBizs()) {
//                        if (bizDTO.getAmount().compareTo(BigDecimal.ZERO) == 0) {
//                            log.info("交易金额Amount为0");
//                        }
//                        BatchTransOrderDetailBiz biz = new BatchTransOrderDetailBiz();
//                        BeanUtils.copyProperties(bizDTO, biz);
//                        biz.setBizType(BusinessTypeEnum.valueOf(bizDTO.getBizTypeStr()).getValue());
//
//                        capitalRefundAll = capitalRefundAll.add(biz.getCapital() == null ? BigDecimal.ZERO : biz.getCapital());
//                        interestRefundAll = interestRefundAll.add(biz.getInterest() == null ? BigDecimal.ZERO : biz.getInterest());
//                        penaltyRefundAll = penaltyRefundAll.add(biz.getPenaltyFee() == null ? BigDecimal.ZERO : biz.getPenaltyFee());
//                        managerFeeRefundAll = managerFeeRefundAll.add(biz.getManageFee() == null ? BigDecimal.ZERO : biz.getManageFee());
//                        guaranteeFeeRefundAll = guaranteeFeeRefundAll.add(biz.getGuaranteeFee() == null ? BigDecimal.ZERO : biz.getGuaranteeFee());
//
//                        AccountBase sourceAccount;
//
//                        //代偿时，出款为是担保账户
//                        if (dto.getTradeType().equals(TransactionTypeEnum.COMPENSATORY.getValue())) {
//                            sourceAccount = accountBaseMapperExt.selectByUserIdAndAccountRole(bizDTO.getSourceUserId(), (byte) UserRoleEnum.GUARANTEECORP.getValue());
//                        } else {
//                            //默认 出款方是借款账户
//                            sourceAccount = accountBaseMapperExt.selectByUserIdAndAccountRole(bizDTO.getSourceUserId(), (byte) UserRoleEnum.BORROWERS.getValue());
//                        }
//                        bizDTO.setSourceAccountNo(sourceAccount.getAccountNo());
//                        AccountBase targetAccount;
//                        if (bizDTO.getAmount().compareTo(BigDecimal.ZERO) > 0 && BusinessTypeEnum.COMMISSION.name().equals(bizDTO.getBizTypeStr())) {
//                            //平台佣金
//                            targetAccount = accountBaseMapperExt.selectByUserIdAndAccountRole(PlatformConstant.PLATFORM_USER_ID, UserRoleEnum.PLATFORM_INCOME.getValue());
//                        } else if ((BusinessTypeEnum.PROFIT.name().equals(bizDTO.getBizTypeStr()) || BusinessTypeEnum.COMPENSATORY_REPAYMENT.name().equals(bizDTO.getBizTypeStr()))) {
//                            //担保服务费 还代偿款
//                            targetAccount = accountBaseMapperExt.selectByUserIdAndAccountRole(bizDTO.getTargetUserId(), UserRoleEnum.GUARANTEECORP.getValue());
//                        } else {
//                            //默认收款方 是投资账户
//                            targetAccount = accountBaseMapperExt.selectByUserIdAndAccountRole(bizDTO.getTargetUserId(), UserRoleEnum.INVESTOR.getValue());
//                        }
//                        if (targetAccount == null){
//                            log.error("目标用户存管账号不存在,userId={}",bizDTO.getTargetUserId());
//                            throw new BizException("目标用户存管账号不存在");
//                        }
//
//                        bizDTO.setTargetAccountNo(targetAccount.getAccountNo());
//                        biz.setId(snowflakeIdWorker.nextId());
//                        biz.setTransDetailOrderId(detail.getId());
//                        biz.setBatchRequestNo(detailDTO.getBatchRequestNo());
//                        biz.setCreateTime(new Date());
//                        biz.setExpectInterest(bizDTO.getExpectInterest());
//                        biz.setSourceAccountNo(sourceAccount.getAccountNo());
//                        biz.setSourceAccountId(sourceAccount.getId());
//                        biz.setTargetAccountNo(targetAccount.getAccountNo());
//                        biz.setTargetAccountId(targetAccount.getId());
//                        biz.setInvestOrderId(bizDTO.getInvestOrderId());
//                        batchTransOrderDetailBizMapperExt.insertSelective(biz);
//                    }
//                }
//            }
//            log.info("add bill Details-for projectId={}--", dto.getProjectId());
//            BillRemark3Enum billRemark3Enum = this.getBillRemark3Enum(dto);
//
//            List<SaveBillDetailRequest> detailRequests = new ArrayList<>();
//            if (capitalRefundAll.compareTo(BigDecimal.ZERO) > 0) {
//                SaveBillDetailRequest detailRequest1 = new SaveBillDetailRequest();
//                detailRequest1.setAmount(capitalRefundAll);
//                if (dto.getTradeType().equals(TransactionTypeEnum.COMPENSATORY.getValue())) {
//                    detailRequest1.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_OUT_PRINCIPAL_SPEED_BORROW);
//                } else {
//                    detailRequest1.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_REPAYMENT_CORPUS);
//                }
//                detailRequest1.setCurrentPeriod(dto.getCurrentPeriod());
//                detailRequest1.setBillRemark3Enum(billRemark3Enum);
//                detailRequests.add(detailRequest1);
//            }
//            if (interestRefundAll.compareTo(BigDecimal.ZERO) > 0) {
//                SaveBillDetailRequest detailRequest2 = new SaveBillDetailRequest();
//                detailRequest2.setAmount(interestRefundAll);
//                if (dto.getTradeType().equals(TransactionTypeEnum.COMPENSATORY.getValue())) {
//                    detailRequest2.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_OUT_INTEREST);
//                } else {
//                    detailRequest2.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_REPAYMENT_INTEREST);
//                }
//                detailRequest2.setCurrentPeriod(dto.getCurrentPeriod());
//                detailRequest2.setBillRemark3Enum(billRemark3Enum);
//                detailRequests.add(detailRequest2);
//            }
//            if (penaltyRefundAll.compareTo(BigDecimal.ZERO) > 0) {
//                SaveBillDetailRequest detailRequest3 = new SaveBillDetailRequest();
//                detailRequest3.setAmount(penaltyRefundAll);
//                if (dto.getTradeType().equals(TransactionTypeEnum.COMPENSATORY.getValue())) {
//                    detailRequest3.setBillSecondSubjectEnum(BillSecondSubjectEnum.GUARANTEE_AGENCY_ADVANCE_GUARANTEE_OUT_PENALTY);
//                } else {
//                    detailRequest3.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_REPAYMENT_PENALTY);
//                }
//                detailRequest3.setCurrentPeriod(dto.getCurrentPeriod());
//                detailRequest3.setBillRemark3Enum(billRemark3Enum);
//
//                detailRequests.add(detailRequest3);
//            }
//
//            if (managerFeeRefundAll.compareTo(BigDecimal.ZERO) > 0) {
//                SaveBillDetailRequest detailRequest4 = new SaveBillDetailRequest();
//                detailRequest4.setAmount(managerFeeRefundAll);
//                detailRequest4.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_REPAYMENT_MANAGER_FEE);
//                detailRequest4.setCurrentPeriod(dto.getCurrentPeriod());
//                detailRequest4.setBillRemark3Enum(billRemark3Enum);
//                detailRequests.add(detailRequest4);
//            }
//            if (guaranteeFeeRefundAll.compareTo(BigDecimal.ZERO) > 0) {
//                SaveBillDetailRequest detailRequest5 = new SaveBillDetailRequest();
//                detailRequest5.setAmount(guaranteeFeeRefundAll);
//                detailRequest5.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_REPAYMENT_GUARANTEE_FEE);
//                detailRequest5.setCurrentPeriod(dto.getCurrentPeriod());
//                detailRequest5.setBillRemark3Enum(billRemark3Enum);
//
//                detailRequests.add(detailRequest5);
//            }
//            try {
//                String sourceUserId = dto.getTradeType().equals(TransactionTypeEnum.COMPENSATORY.getValue()) ? dto.getGuaranteeUserId() : dto.getBorrowerUserId();
//
//                niiwooBillFacade.saveAccountBillDetailForBase(dto.getBillBaseId(), sourceUserId, detailRequests);
//            } catch (Exception e) {
//                log.error("niiwooBillFacade.saveAccountBillDetailForBase() invoke error,billBaseId={},projectId={}", dto.getBillBaseId(),dto.getProjectId());
//                log.error("error,", e);
//                throw new BizException("ACC30000");
//            }
//
//        }

    }

    private BillRemark3Enum getBillRemark3Enum(AccountBatchTransOrderDTO dto) {
        BillRemark3Enum billRemark3Enum = null;
        if (dto.getBatchRefundType().equals(BatchRefundTypeEnum.OVER_DEBT.getValue())) {
            billRemark3Enum = BillRemark3Enum.REPAYMENT_ADVANCE;
        } else {
            RepayStatusEnum repayStatusEnum = RepayStatusEnum.enumOf(dto.getRepayStatus());
            if (repayStatusEnum!=null) {
                switch (repayStatusEnum.getCode()) {
                    case 1:
                        billRemark3Enum = BillRemark3Enum.REPAYMENT_NORMAL;
                        break;
                    case 2:
                        billRemark3Enum = BillRemark3Enum.REPAYMENT_OVERDUE;
                        break;
                    case 3:
                        billRemark3Enum = BillRemark3Enum.REPAYMENT_OVERDUE_BAD;
                        break;
                    default:
                        billRemark3Enum = BillRemark3Enum.REPAYMENT_NORMAL;
                }
            }
        }
        return billRemark3Enum;
    }


    /**
     * 保存还款预处理订单
     *
     * @param dto
     * @param accountId
     * @param freezePreTransactionRequestNo
     * @return
     */
    @Transactional
    public Long preProcessRepayment(AccountBatchTransOrderDTO dto, Long accountId, String freezePreTransactionRequestNo) {
        //新增预处理订单
        ProTransactionOrder order = new ProTransactionOrder();
        order.setId(snowflakeIdWorker.nextId());
        order.setBatchRequestNo(dto.getBatchRequestNo());
        order.setRequestNo(freezePreTransactionRequestNo);
        order.setAccountId(accountId);
        if (TransactionTypeEnum.COMPENSATORY.getValue().equals(dto.getTradeType())) {
            order.setBizType(PreprocessingBusinessTypeEnum.COMPENSATORY.getValue());
        } else {
            order.setBizType(PreprocessingBusinessTypeEnum.REPAYMENT.getValue());
        }
        order.setAmount(dto.getAmount());
        order.setProjectId(dto.getProjectId());
        order.setStatus(RefundStatusEnum.HANDLING.getValue());
        order.setCreateTime(new Date());
        proTransactionOrderMapperExt.insertSelective(order);
        return order.getId();
    }

    @Transactional
    public void withHoldFailRollBackStatus(String batchNo, Long withHoldOrderId, Long batchTransOrderId) {
        this.updateWithHoldOrderStatus(withHoldOrderId, RefundStatusEnum.FAIL, null);
        this.updateBatchTransOrderStatus(batchNo, batchTransOrderId, RefundStatusEnum.FAIL);
    }
    /**
     * 还款预处理 （冻结）
     *
     * @param orderId 预处理订单号
     * @param accountId
     * @param amount
     * @param dto
     * @return
     */
    @Transactional
    public int updateProTransactionOrderStatusAndAccountAmount(Long orderId, Long accountId, BigDecimal amount, AccountBatchTransOrderDTO dto) {
        //Assert.notNull(request,"对象不可空");
        BatchTransOrder batchTransOrderUpdate = new BatchTransOrder();
        batchTransOrderUpdate.setId(dto.getBatchTransOrderId());
        batchTransOrderUpdate.setProTransOrderId(orderId);
        batchTransOrderMapperExt.updateByPrimaryKeySelective(batchTransOrderUpdate);
        //扣减账户额度,更新预处理订单状态为成功
        int count = this.updateProTransactionOrderStatus(orderId, RefundStatusEnum.SUCCESS);
        if (count == 1) {
            BigDecimal newBalanceAmount = accountBalanceLocalService.decreAccountAmount(accountId, amount);

            SaveAccountBillRequest request = new SaveAccountBillRequest();

            request.setInoutType(InoutTypeEnum.OUT_TYPE);
            //代偿
            if (dto.getTradeType().byteValue() == TransactionTypeEnum.COMPENSATORY.getValue()) {
                request.setBillType(BillUserTypeEnum.GUARANTEE_AGENCY);
                request.setUserId(dto.getGuaranteeUserId());
            } else {
                //还款
                request.setUserId(dto.getBorrowerUserId());
                request.setBillType(BillUserTypeEnum.GENERAL);
            }
            request.setOrderId(orderId);
            request.setAccountId(accountId);
            request.setBalanceAmount(newBalanceAmount);
            request.setProjectId(dto.getProjectId());
            request.setAmount(amount);
            if (dto.getTradeType().byteValue() == TransactionTypeEnum.COMPENSATORY.getValue()) {
                request.setOrderType(OrderTypeEnum.GUARANTEE);
                request.setGuaranteeId(dto.getBatchTransOrderId());
            } else {
                request.setOrderType(OrderTypeEnum.REPAYMENT);
            }
            request.setRequestNo(dto.getFreezeRequestNo());
            request.setStatus(BillStatusEnum.HANDLING);
//            Long billBaseId = niiwooBillFacade.saveAccountBillOnlyBase(request);
//            dto.setBillBaseId(billBaseId);

            //还款冻结+
            List<MoneyTotalDTO> moneyTotalDTOs = new ArrayList<>();
            MoneyTotalDTO refund = new MoneyTotalDTO();
            refund.setAccountId(accountId);
            refund.setUserId(dto.getBorrowerUserId());
            refund.setAmount(amount);
            refund.setAmountType(AccountAmountTypeEnum.REPAYMENT_FREEZE);
            moneyTotalDTOs.add(refund);
            //统计金额更新
            moneyTotalLocalService.moneyTotal(moneyTotalDTOs);
        }
        return count;
    }

    /**
     * 还款预处理 （资金解冻处理）
     *
     * @param orderId 预处理订单号
     * @param accountId
     * @param amount
     * @param dto
     * @return
     */
    @Transactional
    public int rollbackProTransactionOrderStatusAndAccountAmount(Long orderId, Long accountId, BigDecimal amount, AccountBatchTransOrderDTO dto) {
        //回即账户额度,更新预处理订单状态为已删除
        int count = this.delProTransactionOrder(orderId);
        if (count == 1) {
            //关闭账单 + 新增回滚账单 + 变动账户余额
            String sourceUserId;
            if (dto.getTradeType().byteValue() == TransactionTypeEnum.COMPENSATORY.getValue()) {
                //代偿
                billFacade.closeAndRevertBill(orderId + "", OrderTypeEnum.GUARANTEE,"");
                sourceUserId = dto.getGuaranteeUserId();
            } else {
                //还款
                billFacade.closeAndRevertBill(orderId + "", OrderTypeEnum.REPAYMENT,"");
                sourceUserId = dto.getBorrowerUserId();
            }

            //还款冻结+
            List<MoneyTotalDTO> moneyTotalDTOs = new ArrayList<>();
            MoneyTotalDTO refund = new MoneyTotalDTO();
            refund.setAccountId(accountId);
            refund.setUserId(sourceUserId);
            refund.setAmount(amount.negate());
            refund.setAmountType(AccountAmountTypeEnum.REPAYMENT_FREEZE);
            moneyTotalDTOs.add(refund);
            //统计金额更新
            moneyTotalLocalService.moneyTotal(moneyTotalDTOs);
        }
        return count;
    }

    /**
     * 更新还款预处理订单状态
     *
     * @param orderId
     * @param status
     * @return
     */
    @Transactional
    public int updateProTransactionOrderStatus(Long orderId, RefundStatusEnum status) {
        //修改预处理订单状态
        ProTransactionOrder order = new ProTransactionOrder();
        order.setId(orderId);
        order.setStatus(status.getValue());
        return proTransactionOrderMapperExt.updateByPrimaryKeySelectiveInitStatus(order);
    }

    /**
     * 删除还款预处理订单
     *
     * @param orderId
     * @return
     */
    @Transactional
    public int delProTransactionOrder(Long orderId) {
        //修改预处理订单状态
        ProTransactionOrder order = new ProTransactionOrder();
        order.setId(orderId);
        order.setDelFlag((byte)1);
        return proTransactionOrderMapperExt.updateByPrimaryKeySelectiveNotDelStatus(order);
    }

    /**
     * 更新代扣订单状态
     *
     * @param orderId
     * @param status
     * @param type
     * @return
     */
    @Transactional
    public int updateWithHoldOrderStatus(Long orderId, RefundStatusEnum status, OrderEndTypeEnum type) {
        WithholdOrder order = new WithholdOrder();
        order.setId(orderId);
        order.setStatus(status.getValue());
        order.setProxyPretransStatus(status.getValue());
        if (status == RefundStatusEnum.SUCCESS) {
            order.setSuccessTime(new Date());
            if (type != null) {
                order.setEndType(type.getValue());
            }
            return withholdOrderMapperExt.updateWithHoldOrderStatusToSuccess(order);
        }else {
            return withholdOrderMapperExt.updateByPrimaryKeySelective(order);
        }
    }

    /**
     * 代扣(成功后数据处理)
     *
     * @param accountId
     * @param orderId 代扣订单ID
     * @param amount 代扣 金额
     * @param type
     * @param dto
     * @return
     */
    @Transactional
    public int updateWithHoldOrderStatusAndAccountAmount(Long accountId, Long orderId, BigDecimal amount, OrderEndTypeEnum type, AccountBatchTransOrderDTO dto) {
        BatchTransOrder batchTransOrderUpdate = new BatchTransOrder();
        batchTransOrderUpdate.setId(dto.getBatchTransOrderId());
        batchTransOrderUpdate.setWithholdOrderId(orderId);
        batchTransOrderMapperExt.updateByPrimaryKeySelective(batchTransOrderUpdate);
        //修改代扣订单为成功
        int count = this.updateWithHoldOrderStatus(orderId, RefundStatusEnum.SUCCESS, type);
        log.info("修改代扣订单为成功,orderId={},sql影响记录数{}",orderId,count);
        if (count == 1) {

            //变更余额 + 记账
            AddBillDetailDTO addBillDetailDTO = new AddBillDetailDTO();
            addBillDetailDTO.setAmount(amount);
            addBillDetailDTO.setBillSecondSubjectEnum(BillSecondSubjectEnum.USER_RECHARGE);
            addBillDetailDTO.setRemark2(BillRemark3Enum.RECHARGE_TREATY_TYPE.getDesc());

            AddBillAndChangeBalanceDTO billDTO = new AddBillAndChangeBalanceDTO();
            billDTO.setAccountId(accountId);
            billDTO.setAmount(amount);
            billDTO.setInoutType(InoutTypeEnum.IN_TYPE);
            billDTO.setOrderId(orderId);
            billDTO.setOrderType(OrderTypeEnum.RECHARGE_AUTO);
            billDTO.setRequestNo(dto.getWithholdRequestNo());
            billDTO.setStatus(BillStatusEnum.SUCCESS);
            billDTO.setChannelCode(ChannelCodeEnum.APP);
            billDTO.setAddBillDetailDTOList(Arrays.asList(addBillDetailDTO));
            billFacade.addBillAndChangeBalance(billDTO);
            try {
                billFacade.addBillAndChangeBalance(billDTO);
            } catch (Exception e) {
                log.error("代扣保存账单失败.", e);
                throw new BizException("ACC30000");
            }
            WithholdOrder withholdOrder = withholdOrderMapperExt.selectByPrimaryKey(orderId);
            AccountBase accountBase = accountBaseMapperExt.selectByPrimaryKeyForUpdate(accountId);
            this.sendRechargeEventMq(withholdOrder,accountBase);
        }
        return count;
    }

    /**
     * 保存代扣订单
     *
     * @param dto
     * @param account
     * @param card
     * @param payChannel
     * @param orderId
     */
    @Transactional
    public void insertWithHoldOrder(AccountBatchTransOrderDTO dto, AccountBase account, BankCard card, PayChannel payChannel, Long orderId,BigDecimal amount) {
        //插入代扣订单
        WithholdOrder order = new WithholdOrder();
        order.setId(orderId);
        order.setIdCard(card.getIdCard());
        order.setBatchRequestNo(dto.getBatchRequestNo());
        order.setRequestNo(dto.getWithholdRequestNo());
        order.setProxyPretransRequstNo(dto.getProxyPretransRequestNo());
        order.setUserId(dto.getBorrowerUserId());
        order.setAccountId(account.getId());
        order.setBankCardId(card.getId());
        order.setBankCode(card.getBankCode());
        order.setPayChannelId(payChannel.getId());
        order.setMobileNo(card.getMobileNo());
        order.setPayChannelCode(payChannel.getChannelCode());
        order.setAmount(amount);
        order.setStatus(RefundStatusEnum.HANDLING.getValue());
        order.setProxyPretransStatus(RefundStatusEnum.HANDLING.getValue());
        order.setCreateTime(new Date());
        withholdOrderMapperExt.insertSelective(order);
    }


    /**
     * 更新还款订单状态，事物提交后同步更新交易中心状态
     *
     * @param batchNo      批次请求号
     * @param batchOrderId 批次订单号
     * @param status
     * @return
     */
    @Transactional
    public int updateBatchTransOrderStatus(String batchNo, Long batchOrderId, RefundStatusEnum status) {
        BatchTransOrder order = new BatchTransOrder();
        order.setId(batchOrderId);
        order.setStatus(status.getValue());
        int i = batchTransOrderMapperExt.updateByPrimaryKeyHandingSelective(order);
        this.updateBatchTransOrderDetailStatus(batchNo, status);
        if (i>0) {
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                @Override
                public void afterCommit() {
                    super.afterCommit();
                    RpcContext.getContext().asyncCall(new Runnable() {
                        @Override
                        public void run() {
                            repaymentDubboService.updateTransOrderToFailed(batchNo);
                        }
                    });
                }
            });
        }
        return i;
    }




    /**
     * 明细订单状态更新
     *
     * @param batchNo
     * @param status
     * @return
     */
    private int updateBatchTransOrderDetailStatus(String batchNo, RefundStatusEnum status) {
        List<BatchTransOrderDetail> batchList = batchTransOrderDetailMapperExt.selectByDetailByBatchNo(batchNo);
        int i = 0;
        for (BatchTransOrderDetail batchTransOrderDetail : batchList) {
            BatchTransOrderDetail newUpdater = new BatchTransOrderDetail();
            newUpdater.setId(batchTransOrderDetail.getId());
            newUpdater.setStatus(status.getValue());
            int num = batchTransOrderDetailMapperExt.updateByPrimaryKeySelective(newUpdater);
            i = i + num;
        }
        return i;
    }

    @Transactional
    public void freezePreTransactionFailRollBackStatus(Long proTransactionOrderId, Long batchTransOrderId, String batchNo) {
        this.updateProTransactionOrderStatus(proTransactionOrderId, RefundStatusEnum.FAIL);
        this.updateBatchTransOrderStatus(batchNo, batchTransOrderId, RefundStatusEnum.FAIL);
    }

    @Transactional
    public Long insertBatchTransOrder(AccountBatchTransOrderDTO dto) {
        Long orderId = snowflakeIdWorker.nextId();
        BatchTransOrder order = new BatchTransOrder();
        order.setId(orderId);
        order.setBorrowerUserId(dto.getBorrowerUserId());
        order.setBatchRefundType(dto.getBatchRefundType());
        order.setBatchRequestNo(dto.getBatchRequestNo());
        order.setAmount(dto.getAmount());
        order.setTradeType(dto.getTradeType());
        order.setProjectId(dto.getProjectId());
        order.setCurrentPeriod(dto.getCurrentPeriod());
        order.setTotalPeriod(dto.getTotalPeriod());
        order.setProjectTitle(dto.getProjectTitle());
        order.setRepayStatus(dto.getRepayStatus());
        order.setCreateTime(new Date());
        batchTransOrderMapperExt.insertSelective(order);
        return orderId;
    }

    /**
     * 发送充值事件的消息服务(代扣)
     * @param withholdOrder
     * @param accountBase
     */
    public void sendRechargeEventMq(WithholdOrder withholdOrder,AccountBase accountBase) {
        RechargeEventReqDTO rechargeEventReqDTO = new RechargeEventReqDTO();
        rechargeEventReqDTO.setRechargeId(withholdOrder.getId());
        rechargeEventReqDTO.setUserId(withholdOrder.getUserId());
        rechargeEventReqDTO.setUpdateDate(new Date());
        rechargeEventReqDTO.setAmount(withholdOrder.getAmount());
        rechargeEventReqDTO.setBankCode(withholdOrder.getBankCode());

        if(Objects.nonNull(withholdOrder.getPayChannelId())) {
            PayChannel payChannel = payChannelMapperExt.selectByPrimaryKey(withholdOrder.getPayChannelId());
            rechargeEventReqDTO.setPayChannelName(payChannel.getChannelName());
        }else {
            rechargeEventReqDTO.setPayChannelName(null);
        }

        if(Objects.nonNull(withholdOrder.getBankCardId())) {
            BankType bankType = bankTypeMapperExt.selectBankTypeByCode(withholdOrder.getBankCode());
            rechargeEventReqDTO.setBankName(bankType.getBankName());
        }else {
            rechargeEventReqDTO.setBankName(null);
        }

        rechargeEventReqDTO.setRechargeDate(withholdOrder.getCreateTime());
        rechargeEventReqDTO.setRechargeTypeEventEnum(RechargeTypeEventEnum.withhold);
        rechargeEventReqDTO.setUserRoleTypeEventEnum(UserRoleTypeEventEnum.valueOf(accountBase.getAccountRole()));
        RechargeRecordRequestDTO requestDTO = new RechargeRecordRequestDTO();
        requestDTO.setUserId(withholdOrder.getUserId());
        requestDTO.setStatus(withholdOrder.getStatus());
        rechargeEventReqDTO.setFirstRechargeYesOrNoEnum(YesOrNoEnum.NO);

        try {
            rabbitTemplate.convertAndSend(BizEventRabbitConstant.Exchange.BIZ_EVENT_DIRECT_EXCHANGE, BizEventRabbitConstant.Key.BIZ_EVENT_RECHARGE_KEY, rechargeEventReqDTO);
        } catch (AmqpException e) {
            log.error("充值事件同步amountExchangeDTO:{}", JSON.toJSONString(rechargeEventReqDTO), e);
        }
    }

}
